/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 * Description: nic port context
 */

#include <hccl/hccl_types.h>
#include "dlhal_function.h"
#include "dlra_function.h"
#include "sal_pub.h"
#include "adapter_rts.h"
#include "adapter_hccp.h"
#include "network_manager_pub.h"
#include "hccl_network.h"

namespace hccl {
HcclResult NetDevContext::Init(NicType nicType, s32 devicePhyId, s32 deviceLogicId, HcclIpAddress localIp,
    HcclIpAddress backupIp)
{
    devicePhyId_ = devicePhyId;
    deviceLogicId_ = deviceLogicId;
    localIp_ = localIp;
    backupIp_ = backupIp;
    nicType_ = nicType;

    if (nicType == NicType::VNIC_TYPE || nicType == NicType::DEVICE_NIC_TYPE) {
        nicDeployment_ = NICDeployment::NIC_DEPLOYMENT_DEVICE;
    } else {
        nicDeployment_ = NICDeployment::NIC_DEPLOYMENT_HOST;
    }

    if (static_cast<s32>(devicePhyId) == HOST_DEVICE_ID) {
        deviceLogicId_ = 0;
    }

    if (nicDeployment_ == NICDeployment::NIC_DEPLOYMENT_HOST) {
        CHK_RET(NetworkManager::GetInstance(deviceLogicId_).StartHostNet(localIp, hostSocketHandle_));
    }

    return HCCL_SUCCESS;
}

HcclResult NetDevContext::Deinit()
{
    if (nicDeployment_ == NICDeployment::NIC_DEPLOYMENT_HOST) { 
        CHK_RET(NetworkManager::GetInstance(deviceLogicId_).StopHostNet(hostSocketHandle_, localIp_));
    }
    return HCCL_SUCCESS;
}
}

HcclResult HcclNetInit(NICDeployment nicDeploy, s32 devicePhyId, s32 deviceLogicId, bool enableWhitelistFlag,
    bool hasBackup)
{
    CHK_RET(hccl::DlRaFunction::GetInstance().DlRaFunctionInit());
    if (nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
        CHK_RET(hccl::DlHalFunction::GetInstance().DlHalFunctionInit());
        bool isHostUseDevNic;
        CHK_RET(IsHostUseDevNic(isHostUseDevNic));
        u32 tempDevicePhyId = hasBackup ? static_cast<u32>(devicePhyId) : hccl::DEFAULT_PHY_ID;
        HCCL_DEBUG("[%s]start NetworkManager Init, deviceLogicId[%u], devicePhyId[%u], nicDeploy[%d], hasBackup[%d],"
            " tempDevicePhyId[%u]", __func__, deviceLogicId, devicePhyId, nicDeploy, hasBackup, tempDevicePhyId);
        CHK_RET(hccl::NetworkManager::GetInstance(deviceLogicId).Init(
            NICDeployment::NIC_DEPLOYMENT_DEVICE, enableWhitelistFlag, tempDevicePhyId, isHostUseDevNic, hasBackup));
    } else {
        CHK_RET(hccl::NetworkManager::GetInstance(deviceLogicId).Init(
            NICDeployment::NIC_DEPLOYMENT_HOST, enableWhitelistFlag, devicePhyId));
    }

    return HCCL_SUCCESS;
}

HcclResult HcclNetDeInit(NICDeployment nicDeploy, s32 devicePhyId, s32 deviceLogicId, bool hasBackup)
{
    CHK_RET(hccl::NetworkManager::GetInstance(deviceLogicId).DeInit(nicDeploy, false, hasBackup));
    return HCCL_SUCCESS;
}

HcclResult HcclNetOpenDev(
    HcclNetDevCtx *netDevCtx, NicType nicType, s32 devicePhyId, s32 deviceLogicId, hccl::HcclIpAddress localIp,
    hccl::HcclIpAddress backupIp)
{
    CHK_PTR_NULL(netDevCtx);

    hccl::NetDevContext *pNetDevCtx = new (std::nothrow) hccl::NetDevContext();
    CHK_PTR_NULL(pNetDevCtx);

    HcclResult ret = pNetDevCtx->Init(nicType, devicePhyId, deviceLogicId, localIp, backupIp);
    if (ret != HCCL_SUCCESS) {
        HCCL_ERROR("[Init][Port]Init fail. ret[%u]", ret);
        delete pNetDevCtx;
        pNetDevCtx = nullptr;
        return ret;
    }

    *netDevCtx = pNetDevCtx;

    return HCCL_SUCCESS;
}

void HcclNetCloseDev(HcclNetDevCtx netDevCtx)
{
    hccl::NetDevContext* pNetDevCtx = static_cast<hccl::NetDevContext *>(netDevCtx);

    HcclResult ret = pNetDevCtx->Deinit();
    if (ret != HCCL_SUCCESS) {
        HCCL_ERROR("[DeInit][Port]DeInit fail. ret[%u]", ret);
    }

    delete pNetDevCtx;
}

HcclResult HcclNetDevGetNicType(HcclNetDevCtx netDevCtx, NicType *nicType)
{
    CHK_PTR_NULL(netDevCtx);
    hccl::NetDevContext* pNetDevCtx = static_cast<hccl::NetDevContext *>(netDevCtx);

    *nicType = pNetDevCtx->GetNicType();
    return HCCL_SUCCESS;
}

HcclResult HcclNetDevGetLocalIp(HcclNetDevCtx netDevCtx, hccl::HcclIpAddress &localIp)
{
    CHK_PTR_NULL(netDevCtx);
    hccl::NetDevContext* pNetDevCtx = static_cast<hccl::NetDevContext *>(netDevCtx);

    localIp = pNetDevCtx->GetLocalIp();
    return HCCL_SUCCESS;
}

HcclResult HcclNetDevGetPortStatus(HcclNetDevCtx netDevCtx, bool &portStatus)
{
    CHK_PTR_NULL(netDevCtx);
    hccl::NetDevContext* pNetDevCtx = static_cast<hccl::NetDevContext *>(netDevCtx);
    u32 devicePhyId = static_cast<u32>(pNetDevCtx->GetPhyId());
    RdmaHandle rdmaHandle = nullptr;
    enum port_status status;
    CHK_RET(HrtRaRdmaGetHandle(devicePhyId, rdmaHandle));
    CHK_RET(hrtRaRdevGetPortStatus(rdmaHandle, &status));
    portStatus = (status == PORT_STATUS_ACTIVE);
    HCCL_RUN_INFO("[HcclNetDevGetPortStatus]devicePhysicID_[%u], portStatus_[%d]", devicePhyId, portStatus);
    return HCCL_SUCCESS;
}